<template lang="pug">
el-upload(
  ref="uploadFile",
  :class="!imgFlag ? '' : 'avatar-uploader'",
  :list-type="listType",
  :action="actionUrl",
  :file-list="fileList",
  :on-change="fileChange",
  :on-exceed="exceedHandle",
  :before-upload="beforeUpload",
  :on-success="onSuccess",
  :on-preview="onPreview"
  :on-remove="onRemove",
  v-bind="$attrs",
  with-credentials
)
  slot
    el-button.gradientVertical(
      round,
      :size="btnSize",
      v-if="listType !== 'picture-card' && !imgFlag"
    )
      i.mr5.f16(v-if="!noIcon", :class="icon ? icon : 'el-icon-upload'")
      | {{ btnText }}
    span.ml5.f12.c_secondary(v-if="suffix") {{ suffix }}
    template(v-if="imgFlag")
      span.avatar(
        v-for="(item, index) in fileList",
        :style="{ width: avatarStyle.width || '128px', height: avatarStyle.height || '128px' }"
      )
        a-image(
          :key="item.url",
          :url="item.url",
          width="100%",
          height="100%",
          fit="fill"
        )
        span.mask(
          :style="{ lineHeight: avatarStyle.height || '128px' }",
          v-if="!$attrs.disabled"
        )
          i.el-icon-delete(@click.stop="() => removeAsync(index)")
      i.el-icon-plus.avatar-uploader-icon(
        v-if="limit ? fileList.length < limit : true",
        :style="{ width: avatarStyle.width || '128px', height: avatarStyle.height || '128px', lineHeight: avatarStyle.height || '128px' }"
      )
</template>
<script>
import AImage from '../../Image'

export default {
  name: 'UploadFile',
  components: {
    AImage
  },
  props: {
    listType: {
      type: String,
      default: 'text'
    },
    actionUrl: {
      type: String,
      default: '/api/system/upload'
    },
    icon: {
      type: String,
      default: ''
    },
    // 注脚
    suffix: {
      type: String,
      default: ''
    },
    imgFlag: {
      type: Boolean,
      default: false
    },
    noIcon: {
      type: Boolean,
      default: false
    },
    // 初始话已上传文件,对外暴露value属性，用于显示隐藏弹框
    filedList: {
      type: Array,
      default: () => []
    },
    limit: {
      type: Number,
      default: 0
    },
    // 限制文件上传大小
    limitSize: {
      type: Number,
      default: 0
    },
    // 头像样式
    avatarStyle: {
      type: Object,
      default: () => ({})
    },
    btnSize: {
      type: String,
      default: 'large'
    },
    btnText: {
      type: String,
      default: '点击上传'
    },
    changeHandle: {
      type: Function,
      default: null
    },
    success: {
      type: Function,
      default: null
    },
    remove: {
      type: Function,
      default: null
    },
    progress: {
      type: Function,
      default: null
    },
    change: {
      type: Function,
      default: null
    }
  },
  data () {
    return {
      // fileList: [...this.filedList]
    }
  },
  computed: {
    fileList: {
      get () {
        const filedList = this.filedList.map((x) => {
          if (x.response && x.response.code === this.$successCode) {
            x.url = x.response.data.url
          } else if (!x.url && x.raw) {
            x.url = URL.createObjectURL(x.raw)
          }
          return x
        })
        return [...filedList]
      },
      set (val) {
        this.$emit('update:filedList', val)
      }
    }
  },
  methods: {
    fileChange (file, fileList) {
      this.fileList = fileList
      this.$emit('change', fileList)
    },
    onSuccess (response, file, fileList) {
      console.log(file, fileList)
      this.fileList = fileList
      if (this.success) {
        this.success({ response, file, fileList })
      }
      this.$emit('success', fileList)
    },
    onRemove (file, fileList) {
      console.log(fileList)
      this.fileList = fileList
      if (this.remove) {
        this.remove({ file, fileList })
      }
      this.$emit('remove', file)
    },
    removeAsync (index) {
      const { fileList } = this
      fileList.splice(index, 1)
      console.log(fileList)
      this.fileList = [...fileList]
    },
    exceedHandle () {
      this.$message.error('文件超出个数限制')
    },
    onPreview (e) {
      const validTypes = ['video', 'mp4']
      if (!validTypes.includes(e?.type?.toLowerCase())) return
      if (e?.url) {
        window.open(e.url)
      }
    },
    beforeUpload (file) {
      const { limitSize, limit, actionUrl, rest } = this.$props
      const { fileList } = this
      return new Promise((resolve, reject) => {
        const total = fileList.length + 1

        for (let i = 0; i < fileList.length; i++) {
          if (
            fileList[i].originFileObj &&
            fileList[i].originFileObj.name === file.name &&
            fileList[i].originFileObj.size === file.size
          ) {
            this.$message.error('请不要上传重复附件', 2)
            reject(new Error())
          }
        }

        // 判断上传个数
        if (limit && total > limit) {
          this.$message.error('最多只能上传' + limit + '张', 2)
          reject(new Error())
          return
        }

        // 判断上传文件大小
        if (limitSize && file.size / 1024 / 1024 > limitSize) {
          this.$message.error('文件大小不能超过 ' + limitSize + 'MB!')
          reject(new Error())
          return
        }
        // 判断是否执行上传拦截
        if (!actionUrl) {
          // // 根据后台需求数据格式
          // const form = new FormData()
          // // 文件对象
          // form.append(name, file)
          // 项目封装的请求方法，下面做简单介绍
          this.$emit('uploadFile', file, rest)
          reject(new Error())
          return
        }
        this.$emit('beginUpload', fileList)
        resolve()
      })
    }
  }
}
</script>
<style lang="scss" scoped>
.avatar-uploader {
  .el-upload {
    border: 1px dashed #d9d9d9;
    border-radius: 6px;
    cursor: pointer;
    position: relative;
    overflow: hidden;
  }
}
.avatar-uploader .el-upload:hover {
  // border-color: #409EFF;
}
.avatar-uploader-icon {
  font-size: 28px;
  color: #8c939d;
  width: 128px;
  height: 128px;
  line-height: 128px;
  text-align: center;
  border: 1px dashed $--border-color-light;
  border-radius: 3px;
  background: #fafafa;
}
.avatar {
  width: 128px;
  height: 128px;
  display: inline-block;
  position: relative;

  + .avatar,
  + .avatar-uploader-icon {
    margin-right: 10px;
  }

  .mask {
    display: none;
    position: absolute;
    background: rgba(0, 0, 0, 0.6);
    color: #fff;
    left: 0;
    top: 0;
    width: 100%;
    height: 100%;
    text-align: center;
    line-height: 128px;

    i {
      font-size: 24px;
    }
  }

  &:hover {
    .mask {
      display: block;
    }
  }
}
</style>
